package com.lrkj.payfee.service.impl;

import com.lrkj.common.constant.FeeConstants;
import com.lrkj.common.core.domain.entity.SysUser;
import com.lrkj.common.utils.DateUtils;
import com.lrkj.common.utils.NumberArithmeticUtils;
import com.lrkj.common.utils.SecurityUtils;
import com.lrkj.common.utils.StringUtils;
import com.lrkj.common.utils.uuid.IdUtils;
import com.lrkj.framework.utils.SerialNumUtil;
import com.lrkj.payfee.domain.*;
import com.lrkj.payfee.mapper.AdvicePaymentMapper;
import com.lrkj.payfee.service.*;
import com.lrkj.payfee.vo.TooReceiptVo;
import com.lrkj.property.domain.Room;
import com.lrkj.property.service.IRoomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 付款单Service业务层处理
 *
 * @author yajun_ren
 * @date 2022-03-26
 */
@Service
public class AdvicePaymentServiceImpl implements IAdvicePaymentService {
    @Autowired
    private AdvicePaymentMapper advicePaymentMapper;

    @Autowired
    private IRoomService roomService;

    @Autowired
    private IAdvicePaymentDetailService advicePaymentDetailService;

    @Autowired
    private IReceiptDetailService receiptDetailService;

    @Autowired
    private IAdvanceReceiptService advanceReceiptService;

    @Autowired
    private IAgainstRecordService againstRecordService;

    @Autowired
    private IAdvicePaymentModeService advicePaymentModeService;

    /**
     * 查询付款单
     *
     * @param id 付款单ID
     * @return 付款单
     */
    @Override
    public AdvicePayment selectAdvicePaymentById(String id) {
        return advicePaymentMapper.selectAdvicePaymentById(id);
    }

    /**
     * 查询付款单列表
     *
     * @param advicePayment 付款单
     * @return 付款单
     */
    @Override
    public List<AdvicePayment> selectAdvicePaymentList(AdvicePayment advicePayment) {
        return advicePaymentMapper.selectAdvicePaymentList(advicePayment);
    }

    /**
     * 新增付款单
     *
     * @param advicePayment 付款单
     * @return 结果
     */
    @Override
    @Transactional
    public int insertAdvicePayment(AdvicePayment advicePayment) {

        if (advicePayment.getBusinessType().equals(FeeConstants.BUSINESS_TYPE_RECEIPT)) {
            //收款单
            this.tooReceipt(advicePayment);
        } else if (advicePayment.getBusinessType().equals(FeeConstants.BUSINESS_TYPE_ADVANCE_RECEIPT)) {
            //预收单
            this.tooAdvanceReceipt(advicePayment);
        } else if (advicePayment.getBusinessType().equals(FeeConstants.BUSINESS_TYPE_PLEDGE_RECEIPT)) {
            //保证金
//            this.tooBailReceipt(advicePayment);
        }

        //新增付款方式
        List<AdvicePaymentMode> modePayments = advicePayment.getModePayments();
        if (null != modePayments && modePayments.size() > 0) {
            modePayments.stream().forEach(x -> {
                x.setId(IdUtils.simpleUUID());
                x.setAdvicePaymentId(advicePayment.getId());
                x.setPaymentTime(DateUtils.getNowDate());
                x.setPaymentUserName(advicePayment.getPaymentUserName());
                x.setCreateBy(SecurityUtils.getUsername());
                x.setCreateTime(DateUtils.getNowDate());
            });
            advicePaymentModeService.doSaveList(modePayments);
        }

        return 1;
    }


    //退预收单
    private void tooAdvanceReceipt(AdvicePayment advicePayment) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Room room = roomService.selectRoomById(advicePayment.getRoomId());
        advicePayment.setId(IdUtils.simpleUUID());
        advicePayment.setPaymentTime(DateUtils.getNowDate());//付款日期
        advicePayment.setPaymentUserId(user.getUserId() + "");//付款人ID
        advicePayment.setPaymentUserName(user.getNickName());//付款人名称
        advicePayment.setNo(SerialNumUtil.getNo("FKD"));//付款单号
        advicePayment.setStatus(FeeConstants.advice_payment_status_20);
        advicePayment.setAncestors(room.getAncestors());
        List<AdvicePaymentDetail> saveDetails = new ArrayList<>();
        List<String> customIds = new ArrayList<>();
        List<String> customNames = new ArrayList<>();
        //1、
        if (advicePayment.getAdvanceReceipts().size() > 0) {
            advicePayment.getAdvanceReceipts().stream().forEach(advanceReceipt -> {
                if (!customIds.contains(advanceReceipt.getOwnerId())) {
                    customIds.add(advanceReceipt.getOwnerId());
                }
                if (!customNames.contains(advanceReceipt.getOwnerName())) {
                    customNames.add(advanceReceipt.getOwnerName());
                }
                //付款单明细
                AdvicePaymentDetail detail = this.advicePaymentDetailFactory(advanceReceipt);
                detail.setPaymentTime(advicePayment.getPaymentTime());//付款日期
                detail.setAdvicePaymentId(advicePayment.getId());
                saveDetails.add(detail);
                //更新预收款
                this.updateAdvanceReceipt(advanceReceipt, advicePayment);
            });
            advicePayment.setCustomIds(StringUtils.join(customIds, ","));//客户IDS
            advicePayment.setCustomName(StringUtils.join(customNames, ","));//客户名称
        }
        advicePayment.setCreateTime(DateUtils.getNowDate());
        advicePayment.setCreateBy(user.getNickName());
        //付款方式
        //TODO
        advicePaymentDetailService.doSaveList(saveDetails);
        advicePaymentMapper.insertAdvicePayment(advicePayment);

    }

    //退预收款  付款单明细工厂
    private AdvicePaymentDetail advicePaymentDetailFactory(AdvanceReceipt advanceReceipt) {
        AdvicePaymentDetail detail = new AdvicePaymentDetail();
        detail.setId(IdUtils.simpleUUID());
        detail.setCopeYearMonth(DateUtils.dateTimeNow(DateUtils.YYYY_MM));//应付年月
        detail.setPaymentItemsId(FeeConstants.payment_items_tysk);//付款项目 退预收款
        detail.setPaymentMoney(advanceReceipt.getDrawbackMoney());//现付金额
        detail.setCopeRemark("");//应付说明
        detail.setNoteRemark("");//扣款说明
        detail.setBusinessId(advanceReceipt.getMadvanceReceiptId());//业务ID
        detail.setBusinessType(FeeConstants.BUSINESS_TYPE_ADVANCE_RECEIPT);//业务类型
        detail.setBusinessNo(advanceReceipt.getNo());//业务单号


        return detail;
    }

    //更新预收款
    private void updateAdvanceReceipt(AdvanceReceipt advanceReceipt, AdvicePayment advicePayment) {
        AdvanceReceipt oldAdvanceReceipt = advanceReceiptService.selectAdvanceReceiptById(advanceReceipt.getMadvanceReceiptId());
        //剩余可退金额 -  退款金额
        BigDecimal refundAmount = NumberArithmeticUtils.safeSubtract(oldAdvanceReceipt.getAmountRemaining(), advanceReceipt.getDrawbackMoney());
        oldAdvanceReceipt.setAmountRemaining(refundAmount);//剩余可退金额
        oldAdvanceReceipt.setDrawbackMoney(NumberArithmeticUtils.safeAdd(oldAdvanceReceipt.getDrawbackMoney(), advanceReceipt.getDrawbackMoney()));//退款总金额
        if (refundAmount.compareTo(BigDecimal.ZERO) == 0) {
            oldAdvanceReceipt.setStatus(FeeConstants.advance_receipt_status_10003);//全部使用
        } else {
            oldAdvanceReceipt.setStatus(FeeConstants.advance_receipt_status_10002);//部分使用
        }
        againstRecordService.createAgainstRecord(advanceReceipt.getMadvanceReceiptId(), advicePayment.getId(), "退预收款", advicePayment.getNo(), advanceReceipt.getDrawbackMoney());
        advanceReceiptService.updateAdvanceReceipt(oldAdvanceReceipt);
    }


    //退已收款
    private void tooReceipt(AdvicePayment advicePayment) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Room room = roomService.selectRoomById(advicePayment.getRoomId());
        advicePayment.setId(IdUtils.simpleUUID());
        advicePayment.setPaymentTime(DateUtils.getNowDate());//付款日期
        advicePayment.setPaymentUserId(user.getUserId() + "");//付款人ID
        advicePayment.setPaymentUserName(user.getNickName());//付款人名称
        advicePayment.setNo(SerialNumUtil.getNo("FKD"));//付款单号
        advicePayment.setStatus(FeeConstants.advice_payment_status_20);
        advicePayment.setAncestors(room.getAncestors());
        List<AdvicePaymentDetail> saveDetails = new ArrayList<>();
        List<String> customIds = new ArrayList<>();
        List<String> customNames = new ArrayList<>();
        //1、
        if (advicePayment.getTooReceiptVos().size() > 0) {
            advicePayment.getTooReceiptVos().stream().forEach(receiptVo -> {
                //付款单  付款金额
//                advicePayment.setPaymentMoney(NumberArithmeticUtils.safeAdd(advicePayment.getPaymentMoney(), receiptVo.getDrawbackMoney()));
                if (!customIds.contains(receiptVo.getCustomId())) {
                    customIds.add(receiptVo.getCustomId());
                }
                if (!customNames.contains(receiptVo.getCustomName())) {
                    customNames.add(receiptVo.getCustomName());
                }
                //付款单明细
                AdvicePaymentDetail detail = this.advicePaymentDetailFactory(receiptVo);
                detail.setPaymentTime(advicePayment.getPaymentTime());//付款日期
                detail.setAdvicePaymentId(advicePayment.getId());
                saveDetails.add(detail);
                //更新收款单状态,退款金额,剩余退款金额
            });
            advicePayment.setCustomIds(StringUtils.join(customIds, ","));//客户IDS
            advicePayment.setCustomName(StringUtils.join(customNames, ","));//客户名称
        }
        advicePayment.setCreateTime(DateUtils.getNowDate());
        advicePayment.setCreateBy(user.getNickName());

        //批量新增付款明细
        advicePaymentDetailService.doSaveList(saveDetails);
        //新增付款单
        advicePaymentMapper.insertAdvicePayment(advicePayment);
        //转存金额 新增预收单
        this.changeTransferAmount(advicePayment);
    }


    //退已收款  付款单明细工厂
    private AdvicePaymentDetail advicePaymentDetailFactory(TooReceiptVo tooReceiptVo) {
        AdvicePaymentDetail detail = new AdvicePaymentDetail();
        detail.setId(IdUtils.simpleUUID());
        detail.setCopeYearMonth(DateUtils.dateTimeNow(DateUtils.YYYY_MM));//应付年月
        detail.setPaymentItemsId(tooReceiptVo.getRelevancePayable());//付款项目
        detail.setPaymentMoney(tooReceiptVo.getDrawbackMoney());//现付金额
        detail.setCopeRemark("");//应付说明
        detail.setNoteRemark("");//扣款说明
        detail.setBusinessId(tooReceiptVo.getReceiptDetailId());//业务ID
        detail.setBusinessType(FeeConstants.BUSINESS_TYPE_RECEIPT_DETAIL);//业务类型
        detail.setBusinessNo(tooReceiptVo.getReceiptNo());//业务单号
        detail.setTransferAmount(tooReceiptVo.getTransferAmount());//转存金额
        //更新收款单明细列表
        this.updateReceiptDetail(tooReceiptVo);

        return detail;
    }

    //更新收款单明细状态
    private void updateReceiptDetail(TooReceiptVo tooReceiptVo) {
        ReceiptDetail receiptDetail = receiptDetailService.selectReceiptDetailById(tooReceiptVo.getReceiptDetailId());
        //剩余可退金额 -  退款金额 - 转存金额
        BigDecimal refundAmount = NumberArithmeticUtils.safeSubtract(receiptDetail.getRefundAmount(), tooReceiptVo.getDrawbackMoney(), tooReceiptVo.getTransferAmount());
        receiptDetail.setRefundAmount(refundAmount);//剩余可退金额
        receiptDetail.setDrawbackMoney(NumberArithmeticUtils.safeAdd(receiptDetail.getDrawbackMoney(), tooReceiptVo.getDrawbackMoney()));//退款总金额
        receiptDetail.setTransferAmount(NumberArithmeticUtils.safeAdd(receiptDetail.getTransferAmount(), tooReceiptVo.getTransferAmount()));
        if (refundAmount.compareTo(BigDecimal.ZERO) == 0) {
            receiptDetail.setStatus(FeeConstants.receipt_detail_status_30);//全部退款
        } else {
            receiptDetail.setStatus(FeeConstants.receipt_detail_status_20);//部分退款
        }
        receiptDetailService.updateReceiptDetail(receiptDetail);
    }

    //  收款金额转预收
    private void changeTransferAmount(AdvicePayment advicePayment) {
        //转存金额大于0
        if (advicePayment.getTransferAmount().compareTo(BigDecimal.ZERO) > 0) {
            AdvanceReceipt advanceReceipt = new AdvanceReceipt();
            advanceReceipt.setMadvanceReceiptId(IdUtils.simpleUUID());
            advanceReceipt.setNo(SerialNumUtil.getNo("YSK"));
            advanceReceipt.setBillMoney(advicePayment.getTransferAmount());//转存金额
            advanceReceipt.setBillTime(DateUtils.getNowDate());
            advanceReceipt.setOwnerId(advicePayment.getCustomIds());
            advanceReceipt.setRoomId(advicePayment.getRoomId());
            advanceReceipt.setCreateBy(SecurityUtils.getUsername());
            advanceReceipt.setCreateTime(DateUtils.getNowDate());
            advanceReceipt.setAmountRemaining(advicePayment.getTransferAmount());//剩余金额
            advanceReceipt.setStatus(FeeConstants.advance_receipt_status_10001);
            advanceReceipt.setBusinessId(advicePayment.getId());
            advanceReceipt.setBusinessType(FeeConstants.BUSINESS_TYPE_ADVICE_PAYMENT);
            advanceReceipt.setBusinessNo(advicePayment.getNo());
            advanceReceiptService.insertAdvanceReceipt(advanceReceipt);
        }
    }


    /**
     * 修改付款单
     *
     * @param advicePayment 付款单
     * @return 结果
     */
    @Override
    public int updateAdvicePayment(AdvicePayment advicePayment) {
        advicePayment.setUpdateTime(DateUtils.getNowDate());
        return advicePaymentMapper.updateAdvicePayment(advicePayment);
    }

    /**
     * 批量删除付款单
     *
     * @param ids 需要删除的付款单ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteAdvicePaymentByIds(String[] ids) {
        AdvicePayment eg = new AdvicePayment();
        eg.getParams().put("ids", ids);
        List<AdvicePayment> advicePayments = advicePaymentMapper.selectAdvicePaymentList(eg);
        advicePayments.stream().forEach(x -> {
            //付款单明细
            List<AdvicePaymentDetail> advicePaymentDetails = x.getAdvicePaymentDetails();
            //付款单明细IDS
            List<String> advicePaymentDetailIds = advicePaymentDetails.stream().map(AdvicePaymentDetail::getId).collect(Collectors.toList());
            //业务 ids
            List<String> businessIds = advicePaymentDetails.stream().map(AdvicePaymentDetail::getBusinessId).collect(Collectors.toList());
            //付款单
            if (x.getBusinessType().equals(FeeConstants.BUSINESS_TYPE_ADVICE_PAYMENT)) {

                List<ReceiptDetail> receiptDetails = receiptDetailService.selectReceiptDetailByIds(businessIds.toArray(new String[]{}));
                advicePaymentDetails.stream().forEach(detail -> {
                    BigDecimal paymentMoney = NumberArithmeticUtils.safeAdd(detail.getPaymentMoney(), detail.getTransferAmount());
                    List<ReceiptDetail> collect = receiptDetails.stream().filter(receiptDetail -> receiptDetail.getReceiptDetailId().equals(detail.getBusinessId())).collect(Collectors.toList());
                    if (null != collect && collect.size() > 0) {
                        ReceiptDetail receiptDetail = collect.get(0);
                        //剩余可退金额 付款单退款金额 + 转存金额
                        receiptDetail.setRefundAmount(NumberArithmeticUtils.safeAdd(receiptDetail.getRefundAmount(), paymentMoney));
                        //退款金额
                        receiptDetail.setDrawbackMoney(NumberArithmeticUtils.safeSubtract(receiptDetail.getDrawbackMoney(), paymentMoney));
                        receiptDetailService.updateReceiptDetail(receiptDetail);
                    }
                    //转存金额大于0 意味着生成的有预收单
                    if (detail.getTransferAmount().compareTo(BigDecimal.ZERO) > 0) {
                        //通过付款单明细ID 删除预收单
                        advanceReceiptService.deleteByBusinessIds(advicePaymentDetailIds.toArray(new String[]{}));
                    }
                });
                //删除付款单明细
                advicePaymentDetailService.deleteAdvicePaymentDetailByIds(advicePaymentDetailIds.toArray(new String[]{}));
            } else if (x.getBusinessType().equals(FeeConstants.BUSINESS_TYPE_ADVANCE_RECEIPT)) {
                //查询预收单列表
                AdvanceReceipt advanceReceiptEg = new AdvanceReceipt();
                advanceReceiptEg.getParams().put("madvanceReceiptIds", businessIds);
                List<AdvanceReceipt> advanceReceipts = advanceReceiptService.selectAdvanceReceiptList(advanceReceiptEg);
                advicePaymentDetails.stream().forEach(detail -> {
                    BigDecimal paymentMoney = NumberArithmeticUtils.safeAdd(detail.getPaymentMoney(), detail.getTransferAmount());
                    List<AdvanceReceipt> collect = advanceReceipts.stream().filter(advanceReceiptDetail -> advanceReceiptDetail.getMadvanceReceiptId().equals(detail.getBusinessId())).collect(Collectors.toList());
                    if (null != collect && collect.size() > 0) {
                        AdvanceReceipt receiptDetail = collect.get(0);
                        //剩余可退金额 付款单退款金额 + 转存金额
                        receiptDetail.setAmountRemaining(NumberArithmeticUtils.safeAdd(receiptDetail.getAmountRemaining(), paymentMoney));
                        //退款金额
                        receiptDetail.setDrawbackMoney(NumberArithmeticUtils.safeSubtract(receiptDetail.getDrawbackMoney(), paymentMoney));
                        x.setStatus(FeeConstants.advance_receipt_status_10002);
                        advanceReceiptService.updateAdvanceReceipt(receiptDetail);
                        //预收冲记录
                        againstRecordService.createAgainstRecord(receiptDetail.getMadvanceReceiptId(), detail.getId(), "退预收款(单据删除)", detail.getBusinessNo(), paymentMoney);
                    }
                });
                //删除付款单明细
                advicePaymentDetailService.deleteAdvicePaymentDetailByIds(advicePaymentDetailIds.toArray(new String[]{}));
            }
        });
        //删除所有的付款单
        return advicePaymentMapper.deleteAdvicePaymentByIds(ids);
    }

    /**
     * 删除付款单信息
     *
     * @param id 付款单ID
     * @return 结果
     */
    @Override
    public int deleteAdvicePaymentById(String id) {
        return advicePaymentMapper.deleteAdvicePaymentById(id);
    }

    @Override
    public List<TooReceiptVo> tooReceiptlist(TooReceiptVo tooReceiptVo) {
        return advicePaymentMapper.tooReceiptlist(tooReceiptVo);
    }

    /**
     * 批量新增付款单信息
     *
     * @param advicePayments 付款单对象
     */
    public int batchAddData(List<AdvicePayment> advicePayments) {
        return advicePaymentMapper.batchAddData(advicePayments);
    }
}
